﻿#include"stdafx.h"
#ifdef LK_MOBJECT_
namespace LK
{
	ptr<Type> MObjects::GetType()const { return Type::Make<PMObjects>(); }
	/**
	@brief 获取内部类型*/
	ptr<Type> MObjects::GetInnerType()const { return (ptr<Type> const&)innerDataType; }
	void MObjects::AddTypeInfo()
	{
#ifdef LK_REFLECTION_
		using namespace Reflection;
		using namespace Functional;
		//获取全局命名空间
		PNamespaceNode space = GetGlobleLibrary().GetGlobleNamespaceRef().FindOrAddNamespace(L"LK");
		//查找或添加ptr<Time>类型节点
		PTypeNode node = space.FindOrAddTypeNode(L"MObjects", Type::Make<PMObjects>());
		//设置继承关系
		node.AddBaseType(Type::Make<ptr<Object>>());
#endif
	}
	/**
	@brief 获取内部数据指针，该方法常用以直接修改引用型封箱*/
	void*MObjects::GetDataPtr(PObject const& p) {
		if (p->GetType() != Type::Make<PMObjects>())return &(size_t&)p;
		return ((PMObjects&)p)->GetDataPtr();
	}
	/**
	@brief 获取所表示的对象的指针，该方法常用以获取对象数值*/
	void*MObjects::GetObjectPtr(PObject const& p)
	{
		if (p->GetType() != Type::Make<PMObjects>())return null;
		return ((PMObjects&)p)->GetObjectPtr();
	}
	void* MObjects::GetObjectPtr()
	{
		if (innerDataType!=null)
		{
			if (GetInnerType()->IsArray() || GetInnerType()->IsLValueReference() || (GetInnerType()->IsFunction() && GetInnerType()->GetID() == 0))
				return *(void**)GetDataPtr();//存的地址，需要解引用
		}
		return GetDataPtr();//存的副本
	}
	//获取
#define _TMP(t) case t+(sizeof(size_t)>4):x = new MObject<(1ull<<(t+(sizeof(size_t)>4))) - sizeof(MObject <0>) - 4 * sizeof(size_t)>();break;
	PMObjects MObjects::MakeMObjectByTypeInfo(ptr<Type> const&t, const void* p)
	{
		PMObjects x;
		if (t == Type::Make<void>())return x;
		switch (sizeof(size_t) * 8 - Bits::LeftZeroCount((size_t)(t->GetSize() + sizeof(MObject <0>) + 5 * sizeof(size_t) - 1)))
		{
			MF3_RepeatAsc(_TMP,6, 30);
		default:break;
		}
		x->innerDataType = t;
		if (p)t->CopyConstruct(x->GetDataPtr(), p);
		else t->DefaultConstruct(x->GetDataPtr());
		return x;
	}
	PMObjects MObjects::MakeMObjectByTypeInfo(const void*pobj, ptr<Type> const&t)
	{
		if (!pobj)Throw<PPointerIsNullException >();
		if (!t->IsLValueReference())return MakeMObjectByTypeInfo(t, pobj);
		PMObjects x;
		switch (sizeof(size_t) * 8 - Bits::LeftZeroCount((size_t)(t->GetSizeIgnoreReference() + sizeof(void*) + sizeof(MObject <0>) + 5 * sizeof(size_t) - 1)))
		{
			MF3_RepeatAsc(_TMP,6, 30);
		default:break;
		}
		x->innerDataType = t;
		t->CopyConstructIgnoreReference((u8*)x->GetDataPtr() + sizeof(void*), pobj);
		*(void**)x->GetDataPtr() = (*(void**)((u8*)x->GetDataPtr() - sizeof(void*))) = (u8*)x->GetDataPtr() + sizeof(void*);
		return x;
	}
	MObjects* MObjects::Clone()const { return MObjects::MakeMObjectByTypeInfo(GetInnerType(), ((MObjects*)this)->GetDataPtr()).GetPtr(); }
	bool MObjects::IsCopy()const
	{
		if (((MObjects*)this)->GetDataPtr() && ((MObject<4>*)this)->ptmp)return true;
		return !GetInnerType()->IsArray() && !GetInnerType()->IsLValueReference() && !(GetInnerType()->IsFunction() && GetInnerType()->GetID() == 1);
	}

#undef _TMP
}
#endif